/***********************************
* Name: Gate.java
* Date: Aug 7, 2010
* @author martin
* @author karen
* Description:
***********************************/

import javax.swing.ImageIcon;

public class Gate {

    public final static int POINTER  = 0;
    public final static int NOT  = 1;
    public final static int AND  = 2;
    public final static int OR   = 3;
    public final static int NAND = 4;
    public final static int NOR  = 5;

    private String  name;
    private int     type;
    private Input   A;
    private Input   B;
    private boolean output;
    private int     x;
    private int     y;
    //to count the names
    private int cont = 1;

    
    /*****************************************
    * Gate
    * Constructor
    *****************************************/
    public Gate(){
        cont = 1;
        while(true){
            this.name = ("G" + this.cont);
            if(MainPanel.existGate(name)==false){
                break;
            }
            this.cont++;
        }

        this.type = this.NOT;
        
        
        this.A = new Input();
        this.B = new Input();
        this.output = true;
        this.x = 0;
        this.y = 0;
    }

    /*****************************************
    * Gate
    * @param name
    * @param type
    * @param A
    * @param B
    * @param x
    * @param y
    * @param end
    * Constructor
    * String name, int type, Input A, Input B, boolean end, int x, int y
    *****************************************/
    public Gate(String name, int type, Input A, Input B, int x, int y){

        this.name = name;
        this.type = type;
        this.A = new Input(A.getFallingDelay(), A.getRaisingDelay(), A.getFrom());
        this.B = new Input(B.getFallingDelay(), B.getRaisingDelay(), B.getFrom());
        this.x = x;
        this.y = y;
        this.output = false;
    }

    /*****************************************
     * getTypeString
     * @return String with the type string
     *****************************************/
    public static String getTypeString(int type){
        String stringType="";
        switch(type){
            case POINTER:   stringType = "POINTER"; break;
            case NOT:   stringType = "NOT"; break;
            case AND:   stringType = "AND"; break;
            case OR:    stringType = "OR"; break;
            case NOR:   stringType = "NOR"; break;
            case NAND:  stringType = "NAND"; break;
        }
        return stringType;
    }

    /*****************************************
     * getTypeGateInt
     * @param type
     * @return int with the type of the string
     *****************************************/
    public static int getTypeGateInt(String type){

        if(type.compareToIgnoreCase("pointer")==0){
            return Gate.POINTER;
        }
        if(type.compareToIgnoreCase("not")==0){
            return Gate.NOT;
        }
        if(type.compareToIgnoreCase("and")==0){
            return Gate.AND;
        }
        if(type.compareToIgnoreCase("or")==0){
            return Gate.OR;
        }
        if(type.compareToIgnoreCase("nand")==0){
            return Gate.NAND;
        }
        if(type.compareToIgnoreCase("nor")==0){
            return Gate.NOR;
        }
        return -1;
    }

    /*****************************************
     * getTypeGateInt
     * @param type
     * @return int with the type of the string
     *****************************************/
    public static ImageIcon getImageGate(int type){

        ImageIcon icon=null;

        switch(type){
            case NOT:    icon = Main.NOTimage; break;
            case AND:    icon = Main.ANDimage; break;
            case OR:     icon = Main.ORimage; break;
            case NOR:    icon = Main.NORimage; break;
            case NAND:  icon = Main.NANDimage; break;
        }
        
        return icon;
    }

    /*****************************************
     * @return the name
     *****************************************/
    public String getName() {
        return name;
    }

    /*****************************************
     * @param name the name to set
     *****************************************/
    public void setName(String name) {
        this.name = name;
    }

    /*****************************************
     * @return the type
     *****************************************/
    public int getType() {
        return type;
    }

    /*****************************************
     * @param type the type to set
     *****************************************/
    public void setType(int type) {
        this.type = type;
    }

    /*****************************************
     * @return the A
     *****************************************/
    public Input getA() {
        return A;
    }

    /*****************************************
     * @param A the A to set
     *****************************************/
    public void setA(Input A) {
        this.A = A;
    }

    /*****************************************
     * @return the B
     *****************************************/
    public Input getB() {
        return B;
    }

    /*****************************************
     * @param B the B to set
     *****************************************/
    public void setB(Input B) {
        this.B = B;
    }

    /*****************************************
     * @return the end
     *****************************************/
    public boolean isOutput() {
        return output;
    }

    /*****************************************
     * @param end the end to set
     *****************************************/
    public void setOutput(boolean end) {
        this.output = end;
    }

     /*****************************************
     * @return the x
     *****************************************/
    public int getX() {
        return x;
    }

    /*****************************************
     * @param x the x to set
     *****************************************/
    public void setX(int x) {
        this.x = x;
    }

    /*****************************************
     * @return the y
     *****************************************/
    public int getY() {
        return y;
    }

    /*****************************************
     * @param y the y to set
     *****************************************/
    public void setY(int y) {
        this.y = y;
    }


    /*****************************************
     * sensitize
     * @return void
     * sensitize the gate
     *****************************************/
    public void sensitize(char input) {

        switch(type){
            case NOT:
                //not necesary to sensitize
                break;
            case AND: case NAND:
                if(input=='A'){
                    this.B.setValue('1');
                }
                else if(input=='B'){
                    this.A.setValue('1');
                }
                break;
            case OR: case NOR:
                if(input=='A'){
                    this.B.setValue('0');
                }
                else if(input=='B'){
                    this.A.setValue('0');
                }
                break;
        }

    }
    /*****************************************
     * sensitize
     * @return void
     * sensitize the gate
     *****************************************/
    public String getSensitize() {
        return "A: "+this.A.getValue()+" B: "+this.B.getValue();
    }

    /*****************************************
     * resetAnalyze
     * @return void
     * reset the values to analyze
     *****************************************/
    public void resetAnalyze() {

        this.A.resetValue();
        this.B.resetValue();

    }
    
    /*****************************************
     * toString
     * @return String with the content
     * Example:
     * <!-- NAND gate, named C1 -->
     * <Gate	name = "C1" type = "NAND" end = "true">
     *      <input name = "A" fallingDelay = "4" raisingDelay = "3" from = "G1"/>
     *      <input name = "B" fallingDelay = "3" raisingDelay = "5" from = "E1"/>
     *      <position x = "35" y = "40">
     * </Gate>
     *****************************************/
    public String toString() {
        String retorno = "";
        String tab = "\t";

        retorno+=tab+"<!-- "+this.getTypeString(this.type)+" gate, named "+this.getName()+" -->"+"\n";
        //retorno+=tab+"<Gate\tname = \""+this.getName()+"\" type = \""+this.getTypeString(this.type)+"\" end = \""+this.output+"\">"+"\n";
        retorno+=tab+"<Gate\tname = \""+this.getName()+"\" type = \""+this.getTypeString(this.type)+"\">"+"\n";

        //--- input A ---------
        retorno+=tab+tab+"<input name = \"A\" "+this.A.toString()+" />"+"\n";

        //--- input B ---------
        if(this.type != this.NOT && B!=null){
            retorno+=tab+tab+"<input name = \"B\" "+this.B.toString()+" />"+"\n";
        }

        //--- position --------
        retorno+=tab+tab+"<position x = \""+this.getX()+"\" y = \""+this.getY()+"\" />"+"\n";
        
        retorno+=tab+"</Gate>";

        return retorno;
    }
}
